package com.asha.vrlib.plugins.hotspot;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.view.InputDevice;
import android.view.MotionEvent;
import android.view.View;
import com.asha.vrlib.MD360Director;
import com.asha.vrlib.MDVRLibrary;
import com.asha.vrlib.model.MDHitEvent;
import com.asha.vrlib.model.MDHitPoint;
import com.asha.vrlib.model.MDViewBuilder;
import com.asha.vrlib.texture.MD360BitmapTexture;
import com.asha.vrlib.texture.MD360Texture;
import static com.asha.vrlib.common.VRUtil.checkMainThread;
import static com.asha.vrlib.common.VRUtil.notNull;
/**
* Created by hzqiujiadi on 2017/4/12.
* hzqiujiadi ashqalcn@gmail.com
*/
public abstract class MDAbsView extends MDAbsHotspot {
private boolean mInvalidate;
private MD360Texture mTexture;
private View mAttachedView;
private MDLayoutParams mLayoutParams;
private Canvas mCanvas;
private Bitmap mBitmap;
private TouchStatus mTouchStatus;
private enum TouchStatus{
NOP, DOWN
}
public MDAbsView(MDViewBuilder builder) {
super(builder.builderDelegate);
this.mAttachedView = builder.attachedView;
this.mLayoutParams = builder.layoutParams;
this.mAttachedView.setLayoutParams(this.mLayoutParams);
try {
this.mBitmap = Bitmap.createBitmap(mLayoutParams.width, mLayoutParams.height, Bitmap.Config.ARGB_8888);
this.mCanvas = new Canvas(mBitmap);
} catch (Exception e){
e.printStackTrace();
}
requestLayout();
}
public void invalidate(){
if (mBitmap == null){
return;
}
checkMainThread("invalidate must called in main thread.");
notNull(mLayoutParams, "layout params can't be null");
notNull(mAttachedView, "attached view can't be null");
mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
mAttachedView.draw(mCanvas);
mInvalidate = true;
}
public void requestLayout(){
if (mBitmap == null){
return;
}
checkMainThread("requestLayout must called in main thread.");
notNull(mLayoutParams, "layout params can't be null");
notNull(mAttachedView, "attached view can't be null");
mAttachedView.measure(
View.MeasureSpec.makeMeasureSpec(mLayoutParams.width, View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(mLayoutParams.height, View.MeasureSpec.EXACTLY)
);
mAttachedView.layout(0, 0, mAttachedView.getMeasuredWidth(), mAttachedView.getMeasuredHeight());
invalidate();
}
@Override
protected void initInGL(Context context) {
super.initInGL(context);
mTexture = new MD360BitmapTexture(new MDVRLibrary.IBitmapProvider() {
@Override
public void onProvideBitmap(MD360BitmapTexture.Callback callback) {
if (mBitmap != null){
callback.texture(mBitmap);
}
}
});
mTexture.create();
}
@Override
public void renderer(int index, int width, int height, MD360Director director) {
if (mTexture == null || mBitmap == null){
return;
}
if (mInvalidate){
mInvalidate = false;
mTexture.notifyChanged();
}
mTexture.texture(program);
if (mTexture.isReady()){
super.renderer(index, width, height, director);
}
}
@Override
public void onEyeHitIn(MDHitEvent hitEvent) {
super.onEyeHitIn(hitEvent);
MDHitPoint point = hitEvent.getHitPoint();
if (point == null || mAttachedView == null) {
return;
}
int action = mTouchStatus == TouchStatus.NOP ? MotionEvent.ACTION_HOVER_ENTER : MotionEvent.ACTION_HOVER_MOVE;
float x = mAttachedView.getLeft() + mAttachedView.getWidth() * point.getU();
float y = mAttachedView.getTop() + mAttachedView.getHeight() * point.getV();
MotionEvent motionEvent = MotionEvent.obtain(hitEvent.getTimestamp(), System.currentTimeMillis(), action, x, y, 0);
motionEvent.setSource(InputDevice.SOURCE_CLASS_POINTER);
mAttachedView.dispatchGenericMotionEvent(motionEvent);
motionEvent.recycle();
mTouchStatus = TouchStatus.DOWN;
invalidate();
}
@Override
public void onEyeHitOut(long timestamp) {
super.onEyeHitOut(timestamp);
if (mTouchStatus == TouchStatus.DOWN){
MotionEvent motionEvent = MotionEvent.obtain(timestamp, System.currentTimeMillis(), MotionEvent.ACTION_HOVER_EXIT, 0, 0, 0);
motionEvent.setSource(InputDevice.SOURCE_CLASS_POINTER);
mAttachedView.dispatchGenericMotionEvent(motionEvent);
motionEvent.recycle();
}
mTouchStatus = TouchStatus.NOP;
invalidate();
}
public <T extends View> T castAttachedView(Class<T> clazz){
notNull(clazz, "param clz can't be null.");
return clazz.cast(mAttachedView);
}
public View getAttachedView() {
return mAttachedView;
}
}